﻿using KendoMvcUI.Core;
using KendoMvcUI.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KendoMvcUI.Common;

namespace KendoMvcUI.UI.Grid
{
    public class GridSettings:ControlSettingsBase
    {
        public GridSettings()
        {
            Datatype = DataType.json;
            RowNum = 10;
        }
   
        #region 属性
        /// <summary>
        /// This option allows to set global ajax settings for the grid when requesting data. 
        /// Note that with this option it is possible to overwrite all current ajax settings 
        /// in the grid including the error, complete and beforeSend events.
        /// </summary>
        public string AjaxGridOptions { get; set; }
        /// <summary>
        /// This option allows to set global ajax settings for the select element 
        /// when the select is obtained via dataUrl option in editoptions or searchoptions objects
        /// </summary>
        public string AjaxSelectOptions { get; set; }
        
        /// <summary>
        /// 获取数据的地址
        /// </summary>
        public string Url { get; set; }
        /// <summary>
        /// 从服务器端返回的数据类型，默认json。可选类型：xml，local，json，
        /// jsonnp，script，xmlstring，jsonstring，clientside
        /// </summary>
        public DataType Datatype { get; set; }
        /// <summary>
        /// ajax提交方式。POST或者GET，默认GET
        /// </summary>
        public string Mtype { get; set; }
        /// <summary>
        /// 定义翻页用的导航栏，必须是有效的html元素。翻页工具栏可以放置在html页面任意位置
        /// </summary>
        public string Pager { get; set; }
        /// <summary>
        /// 在grid上显示记录条数，这个参数是要被传递到后台
        /// </summary>
        public int RowNum { get; set; }
        /// <summary>
        /// 默认的排序列。可以是列名称或者是一个数字，这个参数会被提交到后台
        /// </summary>
        public string Sortname { get; set; }
        /// <summary>
        /// 定义是否要显示总记录数
        /// </summary>
        public bool? Viewrecords { get; set; }
        /// <summary>
        /// 表格名称
        /// </summary>
        public string Caption { get; set; }
        /// <summary>
        /// 用来指定行显示的css，可以编辑自己的css文件，只有当altRows设为 ture时起作用
        /// </summary>
        public string Altclass { get; set; }
        /// <summary>
        /// 设置表格 zebra-striped 值
        /// </summary>
        public bool? AltRows { get; set; }
        /// <summary>
        /// 对url进行编码
        /// </summary>
        public bool? Autoencode { get; set; }
        /// <summary>
        /// 如果为ture时，则当表格在首次被创建时会根据父元素比例重新调整表格宽度。
        /// 如果父元素宽度改变，为了使表格宽度能够自动调整则需要实现函数：setGridWidth
        /// </summary>
        public bool? Autowidth { get; set; }
        /// <summary>
        /// 启用或者禁用单元格编辑功能
        /// Enables (disables) cell editing. When this option is set to true, 
        /// onSelectRow event can not be used, and hovering is disabled (when mouseover on the rows).
        /// </summary>
        public bool? CellEdit { get; set; }
        /// <summary>
        /// 定义了单元格内容保存位置
        /// Determines where the contents of the cell are saved - can have two values: 'remote' or 'clientArray'. 
        ///If remote the content of the cell if anything is changed is immediately saved to the server using the cellurl property, via ajax. The rowid and the cell content are added to the url by default. If you have the “mtype” setting set to post, the key value pears will be send as post variables. For example, if we save the cell named mycell,{id: rowid, mycell: cellvalue} is added to the url. 
        ///If cellsubmit is 'clientArray', no ajax request is made and the content of the changed cell can be obtained via the method getChangedCells or thru a event.
        /// </summary>
        public string Cellsubmit { get; set; }
        /// <summary>
        /// 单元格提交的url
        /// the url where the cell is to be saved. You need to set this only when you use cellsubmit as 'remote'.
        /// </summary>
        public string Cellurl { get; set; }
        /// <summary>
        /// An array that stores the local data passed to the grid. 
        /// You can directly point to this variable in case you want to load an array data. 
        /// It can replace the addRowData method which is slow on relative big data
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript=true)]
        public List<string> Data { get; set; }
        /// <summary>
        /// xmlstring或者jsonstring
        /// </summary>
        public string Datastr { get; set; }
        /// <summary>
        /// 表格中文字的显示方向，从左向右（ltr）或者从右向左（rtr）
        /// </summary>
        public bool? Direction { get; set; }
        /// <summary>
        /// 定义对form编辑时的url
        /// Defines the url for inline and form editing. May be set to clientArray to manually post data to server
        /// </summary>
        public string Editurl { get; set; }
        /// <summary>
        /// 当返回的数据行数为0时显示的信息。只有当属性 viewrecords 设置为ture时起作用
        /// </summary>
        public string Emptyrecords { get; set; }
        /// <summary>
        /// 当为true时，点击展开行的文本时，treeGrid就能展开或者收缩，不仅仅是点击图片
        /// </summary>
        public bool? ExpandColClick { get; set; }
        /// <summary>
        /// 指定那列来展开tree grid，默认为第一列，只有在treeGrid为true时起作用
        /// </summary>
        public string ExpandColumn { get; set; }
        /// <summary>
        /// If set to true this will place a footer table with one row below the gird records and above the pager. The number of columns equal those specified in colModel
        /// </summary>
        public bool? Footerrow { get; set; }
        /// <summary>
        /// 当为ture时，调整列宽度不会改变表格的宽度。当shrinkToFit 为false时，此属性会被忽略
        /// </summary>
        public bool? ForceFit { get; set; }
        /// <summary>
        /// 定义当前表格的状态：'visible' or 'hidden'
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public GridState? Gridstate { get; set; }
        /// <summary>
        /// 构造一行数据后添加到grid中，如果设为true则是将整个表格的数据都构造完成后
        /// 再添加到grid中，但treeGrid, subGrid, or afterInsertRow 不能用
        /// </summary>
        public bool? Gridview { get; set; }
        /// <summary>
        /// Enables grouping in grid.
        /// </summary>
        public bool? Grouping { get; set; }
        /// <summary>
        /// 表格高度，可以是数字，像素值或者百分比
        /// </summary>
        public int? Height { get; set; }
        /// <summary>
        /// 当为ture时，表格不会被显示，只显示表格的标题。
        /// 只有当点击显示表格的那个按钮时才会去初始化表格数据。
        /// </summary>
        public bool? Hiddengrid { get; set; }
        /// <summary>
        /// 启用或者禁用控制表格显示、隐藏的按钮，只有当caption 属性不为空时起效
        /// </summary>
        public bool? Hidegrid { get; set; }
        /// <summary>
        /// 当为false时mouse hovering会被禁用
        /// </summary>
        public bool? Hoverrows { get; set; }
        /// <summary>
        /// When set, this string is added as prefix to the id of the row when it is built.
        /// </summary>
        public string IdPrefix { get; set; }
        /// <summary>
        /// an array used to add content to the data posted to the server when we are in inline editing.
        /// {}
        /// </summary>
        public string InlineData { get; set; }
        /// <summary>
        /// 当请求或者排序时所显示的文字内容
        /// </summary>
        public string Loadtext { get; set; }
        /// <summary>
        /// 当执行ajax请求时要干什么。disable禁用ajax执行提示；enable默认，
        /// 当执行ajax请求时的提示； block启用Loading提示，但是阻止其他操作
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public LoadUi? Loadui { get; set; }
        /// <summary>
        /// 只有在multiselect设置为ture时起作用，定义使用那个key来做多选。
        /// shiftKey，altKey，ctrlKey
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public MultiKey? Multikey { get; set; }
        /// <summary>
        /// 只有当multiselect = true.起作用，
        /// 当multiboxonly 为ture时只有选择checkbox才会起作用
        /// </summary>
        public bool? Multiboxonly { get; set; }
        /// <summary>
        /// 定义是否可以多选
        /// </summary>
        public bool? Multiselect { get; set; }
        /// <summary>
        /// If set to true enables the multisorting. The options work if the datatype is local. 
        /// In case when the data is obtained from the server the sidx parameter contain the order clause. 
        /// It is a comma separated string in format field1 asc, field2 desc …, fieldN. 
        /// Note that the last field does not not have asc or desc. 
        /// It should be obtained from sord parameter 
        ///When the option is true the behavior is a s follow. 
        ///The first click of the header field sort the field depending on the firstsortoption 
        ///parameter in colModel or sortorder grid parameter. 
        ///The next click sort it in reverse order. The third click removes the sorting from this field
        /// </summary>
        public bool? MultiSort { get; set; }
        /// <summary>
        /// Determines the position of the pager in the grid. 
        /// By default the pager element when created is divided in 3 parts 
        /// (one part for pager, one part for navigator buttons and one part for record information).
        /// default:center
        /// </summary>
        public string pagepos { get; set; }
        /// <summary>
        /// Determines if the Pager buttons should be shown if pager is available. 
        /// Also valid only if pager is set correctly. The buttons are placed in the pager bar.
        /// </summary>
        public bool? Pgbuttons { get; set; }
        /// <summary>
        /// Determines if the input box, where the user can change the number of the requested page, 
        /// should be available. The input box appears in the pager bar.
        /// </summary>
        public bool? Pginput { get; set; }
        /// <summary>
        /// 此数组内容直接赋值到url上，参数类型：{name1:value1…}
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string PostData { get; set; }
        /// <summary>
        /// Determines the position of the record information in the pager. Can be left, center, right.
        /// </summary>
        public string Recordpos { get; set; }
        /// <summary>
        /// 显示记录数信息。{0} 为记录数开始，{1}为记录数结束。viewrecords为ture时才能起效，且总记录数大于0时才会显示此信息
        /// </summary>
        public string Recordtext { get; set; }
        /// <summary>
        /// 个数组用来调整表格显示的记录数，此参数值会替代rowNum参数值传给服务器端。
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public int[] RowList { get; set; }
        /// <summary>
        /// 如果为ture则会在表格左边新增一列，显示行顺序号，从1开始递增。此列名为'rn'.
        /// </summary>
        public bool? Rownumbers { get; set; }
        /// <summary>
        /// When set this parameter can instruct the server to load the total number of rows needed to work on. 
        /// Note that rowNum determines the total records displayed in the grid, 
        /// while rowTotal determines the total number of rows on which we can operate. 
        /// When this parameter is set, we send an additional parameter to the server named totalrows. 
        /// You can check for this parameter, and if it is available you can replace the rows parameter 
        /// with this one. Mostly this parameter can be combined with loadonce parameter set to true.
        /// </summary>
        public int? RowTotal { get; set; }
        /// <summary>
        /// Creates dynamic scrolling grids. When enabled, the pager elements are disabled and 
        /// we can use the vertical scrollbar to load data. 
        /// When set to true the grid will always hold all the items from the start through to 
        /// the latest point ever visited. 
        ///When scroll is set to an integer value (example 1), the grid will just hold the visible lines. 
        ///This allow us to load the data in portions whitout caring about memory leaks. 
        ///In addition to this we have an optional extension to the server protocol: 
        ///npage (see prmNames array). If you set the npage option in prmNames, 
        ///then the grid will sometimes request more than one page at a time; if not, 
        ///it will just perform multiple GET requests. 
        ///Note that this option is not compatible when a grid parameter height is set to auto or 100%.
        /// </summary>
        public bool? Scroll { get; set; }
        /// <summary>
        /// When enabled, selecting a row with setSelection scrolls the grid so that the selected 
        /// row is visible. This is especially useful when we have a verticall scrolling grid and 
        /// we use form editing with navigation buttons (next or previous row). 
        /// On navigating to a hidden row, the grid scrolls so that the selected row becomes visible.
        /// </summary>
        public bool? Scrollrows { get; set; }
        /// <summary>
        /// 此属性用来说明当初始化列宽度时候的计算类型，如果为ture，则按比例初始化列宽度。如果为false，则列宽度使用colModel指定的宽度
        /// </summary>
        public bool? ShrinkToFit { get; set; }
        /// <summary>
        /// 是否可排序
        /// </summary>
        public bool? Sortable { get; set; }
        
        /// <summary>
        /// 是否使用suggrid
        /// </summary>
        public bool? SubGrid { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript=true)]
        public SubGridOptionsSettings SubGridOptions { get; set; }
        /// <summary>
        /// subgrid模型,没有实现
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string SubGridModel { get; set; }
        /// <summary>
        /// 如果为空则使用表格的dataType
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public DataType? SubGridType { get; set; }
        /// <summary>
        /// 加载subgrid数据的url，jqGrid会把每行的id值加到url中
        /// </summary>
        public string SubGridUrl { get; set; }
        /// <summary>
        /// subgrid列的宽度
        /// </summary>
        public int? SubGridWidth { get; set; }
        /// <summary>
        /// This option defines the toolbar of the grid. This is an array with two elements in 
        /// which the first element's value enables the toolbar and the second defines the 
        /// position relative to the body layer (table data). Possible values are top, bottom, 
        /// and both. When we set it like toolbar: [true,”both”] two toolbars are created – one on 
        /// the top of table data and the other at the bottom of the table data. When we have two toolbars, 
        /// then we create two elements (div). The id of the top bar is constructed by concatenating the 
        /// string “t_” and the id of the grid, like “t_” + id_of_the_grid and the id of the bottom toolbar 
        /// is constructed by concatenating the string “tb_” and the id of the grid, like 
        /// “tb_” + id_of_the grid. In the case where only one toolbar is created, we have the id 
        /// as “t_” + id_of_the_grid, independent of where this toolbar is located (top or bottom)
        /// </summary>
        public bool? Toolbar { get; set; }
        /// <summary>
        /// When enabled this option places a pager element at top of the grid, 
        /// below the caption (if available). If another pager is defined, both can coexist and are kept 
        /// in sync. The id of the newly created pager is the combination grid_id + “_toppager”.
        /// </summary>
        public bool? Toppager { get; set; }
        /// <summary>
        /// 启用或者禁用treegrid模式
        /// </summary>
        public bool? TreeGrid { get; set; }
        /// <summary>
        /// treeGrid所使用的方法
        /// </summary>
        public string TreeGridModel { get; set; }
        /// <summary>
        /// 树的图标，默认值：{plus:'ui-icon-triangle-1-e',minus:'ui-icon-triangle-1-s',leaf:'ui-icon-radio-off'}
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public TreeIcons TreeIcons { get; set; }
        /// <summary>
        /// 扩展表格的colModel且加在colModel定义的后面,没有实现
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string TreeReader { get; set; }
        /// <summary>
        /// root元素的级别，
        /// </summary>
        public int? Tree_root_level { get; set; }
        /// <summary>
        /// 从request中取得的一些用户信息
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string UserData { get; set; }
        /// <summary>
        /// 当为true时把userData放到底部，
        /// 用法：如果userData的值与colModel的值相同，那么此列就显示正确的值，如果不等那么此列就为空
        /// </summary>
        public bool? UserDataOnFooter { get; set; }
        
        /// <summary>
        /// 如果设置则按此设置为主，如果没有设置则按colModel中定义的宽度计算
        /// </summary>
        public int? Width { get; set; }
        /// <summary>
        /// 对xml数据结构的描述
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string XmlReader { get; set; }
        #endregion
        #region 事件
        /// <summary>
        /// 当插入每行时触发。rowid插入当前行的id；rowdata插入行的数据，格式为name: value，name为colModel中的名字
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string OnAfterInsertRow { get; set; }
        /// <summary>
        /// 向服务器端发起请求之前触发此事件但如果datatype是一个function时例外
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string OnBeforeRequest { get; set; }
        /// <summary>
        /// 当用户点击当前行在未选择此行时触发。rowid：此行id；e：事件对象。
        /// 返回值为ture或者false。如果返回true则选择完成，如果返回false则不会选择此行也不会触发其他事件
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string OnBeforeSelectRow { get; set; }
        /// <summary>
        /// 当表格所有数据都加载完成而且其他的处理也都完成时触发此事件，排序，翻页同样也会触发此事件
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string OnGridComplete { get; set; }
        /// <summary>
        /// 当从服务器返回响应时执行，xhr：XMLHttpRequest 对象
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string OnLoadComplete { get; set; }
        /// <summary>
        /// 如果请求服务器失败则调用此方法。xhr：XMLHttpRequest 对象；satus：错误类型，字符串类型；error：exception对象
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string OnLoadError { get; set; }
        /// <summary>
        /// 当点击单元格时触发。rowid：当前行id；iCol：当前单元格索引；cellContent：当前单元格内容；e：event对象
        /// </summary>
        public string OnCellSelect { get; set; }
        /// <summary>
        /// 双击行时触发。rowid：当前行id；iRow：当前行索引位置；iCol：当前单元格位置索引；e:event对象
        /// </summary>
        public string OndblClickRow { get; set; }
        /// <summary>
        /// 当点击显示/隐藏表格的那个按钮时触发；gridstate：表格状态，可选值：visible or hidden
        /// </summary>
        public string OnHeaderClick { get; set; }
        /// <summary>
        /// 点击翻页按钮填充数据之前触发此事件，同样当输入页码跳转页面时也会触发此事件
        /// </summary>
        public string OnPaging { get; set; }
        /// <summary>
        /// 在行上右击鼠标时触发此事件。rowid：当前行id；iRow：当前行位置索引；iCol：当前单元格位置索引；e：event对象
        /// </summary>
        public string OnRightClickRow { get; set; }
        /// <summary>
        /// multiselect为ture，且点击头部的checkbox时才会触发此事件。
        /// aRowids：所有选中行的id集合，为一个数组。status：boolean变量说明checkbox的选择状态，
        /// true选中false不选中。无论checkbox是否选择，aRowids始终有 值
        /// </summary>
        public string OnSelectAll { get; set; }
        /// <summary>
        /// 当选择行时触发此事件。rowid：当前行id；status：选择状态，当multiselect 为true时此参数才可用
        /// </summary>
        public string OnSelectRow { get; set; }
        /// <summary>
        /// 当点击排序列但是数据还未进行变化时触发此事件。index：name在colModel中位置索引；
        /// iCol：当前单元格位置索引；sortorder：排序状态：desc或者asc
        /// </summary>
        public string OnSortCol { get; set; }
        /// <summary>
        /// 当开始改变一个列宽度时触发此事件。event：event对象；index：当前列在colModel中位置索引
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string OnResizeStart { get; set; }
        /// <summary>
        /// 当列宽度改变之后触发此事件。newwidth：列改变后的宽度；index：当前列在colModel中的位置索引
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string OnResizeStop { get; set; }
        /// <summary>
        /// 向服务器发起请求时会把数据进行序列化，用户自定义数据也可以被提交到服务器端
        /// </summary>
        [PropertySetting(IsIngoreForJavaScript = true)]
        public string OnSerializeGridData { get; set; }
        #endregion

        #region Columns
        string _cols = "";
        public GridSettings AddColumns(Action<ColumnSettings> column)
        {
            var col = new ColumnSettings();
            column(col);
            if((!_cols.IsNullOrWhiteSpace())&&(!_cols.EndsWith(",")))
                _cols+=",";
            _cols += col.ToJsSettings();
            return this;
        }
        #endregion

        public override string ToJsSettings()
        {
            var js=base.ToJsSettings();
            if (!js.EndsWith(","))
                js += ",";
            #region 属性
            if (RowList != null)
            {
                var rowlist = string.Join(",", RowList);
                js += "rowList:[{0}],".Formator(rowlist);
            }
            if (!PostData.IsNullOrWhiteSpace())
            {
                var postData = PostData;
                if (!PostData.StartsWith("{"))
                    postData = "{" + postData;
                if (!PostData.EndsWith("}"))
                    postData += "}";
                js += "postData:{0},".Formator(postData);
            }
            if (Multikey.HasValue)
                js += "multikey:{0},".Formator(Multikey.Value.ToString());
            if (TreeIcons != null)
                js += TreeIcons.ToString() + ",";
            if (Gridstate.HasValue)
                js += "gridstate:{0},".Formator(Gridstate.Value.ToString());
            if (Loadui.HasValue)
                js += "loadui:{0},".Formator(Loadui.Value.ToString());
            if (SubGridType.HasValue)
                js += "subGridType:{0},".Formator(SubGridType.Value.ToString().LowercaseFirst());
            #endregion

            #region 事件
            if (!OnAfterInsertRow.IsNullOrWhiteSpace())
                js += "afterInsertRow:{0},".Formator(OnAfterInsertRow);
            if (!OnBeforeRequest.IsNullOrWhiteSpace())
                js += "beforeRequest:{0},".Formator(OnBeforeRequest);
            if (!OnBeforeSelectRow.IsNullOrWhiteSpace())
                js += "beforeSelectRow:{0},".Formator(OnBeforeSelectRow);
            if (!OnGridComplete.IsNullOrWhiteSpace())
                js += "gridComplete:{0},".Formator(OnGridComplete);
            if (!OnLoadComplete.IsNullOrWhiteSpace())
                js += "loadComplete:{0},".Formator(OnLoadComplete);
            if (!OnLoadError.IsNullOrWhiteSpace())
                js += "loadError:{0},".Formator(OnLoadError);
            if (!OnResizeStart.IsNullOrWhiteSpace())
                js += "resizeStart:{0},".Formator(OnResizeStart);
            if (!OnResizeStop.IsNullOrWhiteSpace())
                js += "resizeStop:{0},".Formator(OnResizeStop);
            if (!OnSerializeGridData.IsNullOrWhiteSpace())
                js += "serializeGridData:{0},".Formator(OnSerializeGridData);
            #endregion

            #region Column
            js += "colModel:[{0}],".Formator(_cols);
            #endregion

            return js.TrimEnd(',');
        }
    }

    public class TreeIcons
    {
        public string Plus { get; set; }
        public string Minus { get; set; }
        public string Leaf { get; set; }

        public override string ToString()
        {
            string treeIcon="";
            if (!Plus.IsNullOrWhiteSpace())
                treeIcon += "plus:'{0}',".Formator(Plus);
            if (!Minus.IsNullOrWhiteSpace())
                treeIcon += "minus:'{0}',".Formator(Minus);
            if (!Leaf.IsNullOrWhiteSpace())
                treeIcon += "leaf:'{0}',".Formator(Leaf);

            return "treeIcons:{{0}}".Formator(treeIcon.TrimEnd(','));
        }
    }
}
